#include "stdafx.h"
#include "DriveStream.h"

using namespace System;
using namespace IO;
using namespace Exception;

DriveStream::DriveStream(DriveInfo driveInfo, DriveType type, char* name)
{
	init(name);
	m_driveInfo = driveInfo;
	m_driveType = type;
}

void DriveStream::init(const char* name)
{	
    m_diskName = new char[1 + strlen(name)];
	memcpy (m_diskName, name, (1 + strlen(name)) * sizeof(char));
#ifdef WIN32
	m_handle = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
		0, OPEN_EXISTING, 0, 0);
	if (m_handle == INVALID_HANDLE_VALUE) 
	{ 
		MessageBox(0, "Could not open disk drive", "Error",  MB_OK|MB_ICONINFORMATION);
		m_openSuccesfull = false;
	}
	else
	{
		m_openSuccesfull = true;
	}
#else

#endif
}

DriveStream::~DriveStream(void)
{
	delete m_diskName; 
	if (m_openSuccesfull)
	{
#ifdef WIN32
		CloseHandle(m_handle);
#endif
	}
}

//offset from the current disk pointer!
//always 0 for now
//returns ERROR_SUCCESS or -1
//the size of the buffer will lie in the memBuf
int   DriveStream::read(MemoryBuffer& memBuf, int offset, size_t count)
{
#ifdef WIN32
	DWORD bytes;
    memBuf.updateSize(count);
	DWORD	nRet = ReadFile(m_handle, memBuf.getData(), count, &bytes, 0);
	
	if(!nRet)
		return GetLastError();

	return bytes;
#else
	return 0;
#endif
}

int   DriveStream::readByte(byte& value)
{
	//this is not used
	return 0;
}

ud_uint64 DriveStream::seek(ud_uint64 offset)
{
	LARGE_INTEGER		sectorPos;
	sectorPos.QuadPart	=	offset;
	DWORD crtFilePtr = SetFilePointer(m_handle, sectorPos.LowPart, &sectorPos.HighPart, FILE_BEGIN);
	return offset;
}

ud_uint64 DriveStream::seek(ud_uint64 offset, SeekOrigin origin) 
{
	//TODO
	throw(ExceptionBase (L""));
//	switch (m_driveType)
//	{
//	case NTFS:
//		_offset = (ud_uint64)m_driveInfo.NTRelativeSector*m_driveInfo.bytesPerSector;
//		_offset += (ud_uint64)(((offset * m_driveInfo.sectorPerluster) << 9)) ;
//#ifdef WIN32
//		LARGE_INTEGER		sectorPos;
//		sectorPos.QuadPart	=	_offset;
//		DWORD crtFilePtr = SetFilePointer(m_handle, sectorPos.LowPart, &sectorPos.HighPart, FILE_BEGIN);
//#else
//		//TODO Linux stuff
//#endif
//		if (crtFilePtr	==	INVALID_SET_FILE_POINTER)
//		{
//			throw IODriveException(L"SetFilePointer failed");
//		}
//		return _offset;
//	}

	return (ud_uint64)-1;
}

void  DriveStream::setLength(ud_uint64 value)
{
	throw Exception::IODriveException(L"Can set lenght on a drive");
}

int  DriveStream::write(const MemoryBuffer& memBuf, int offset, size_t count)
{
	throw Exception::IODriveException(L"Can't write to drive");
}

void  DriveStream::writeByte(byte value)
{
	throw Exception::IODriveException(L"Can't write to drive");
}
	
void DriveStream::initDriveInformation(DriveInfo driveInfo)
{
	m_driveInfo = driveInfo;
}